package webx;

import stdx.Utils;
import stdx.ConfigFile;
import java.util.ArrayList;

import dbx.DBConnect;
import dbx.RedisConnect;
import webx.http.HttpRequest;
import webx.http.HttpResponse;

public class Startup extends WebApp{
    public static class DBConfig{
        int port;
        String id;
        String host;
        String type;
        String name;
        String user;
        String passwd;
    }

	private static int dbconnmaxlen = 8;
	private static int dbconntimeout = 60;

	@SuppressWarnings("unchecked")
	public byte[] getCgiPath(byte[] path){
		try{
			String tmp = new String(path);

			tmp = tmp.replace('/', '.');
			tmp = tmp.replace('\\', '.');

			Class clazz = Class.forName(tmp);
			Path cgipath = (Path)clazz.getAnnotation(Path.class);
            Document document = (Document)clazz.getAnnotation(Document.class);
			TimerTask timertask = (TimerTask)clazz.getAnnotation(TimerTask.class);
			DailyTask dailytask = (DailyTask)clazz.getAnnotation(DailyTask.class);

			if (cgipath == null) return null;

			tmp = cgipath.value();
			String name = clazz.getName();
			int pos = name.lastIndexOf('.');
			if (pos > 0) name = name.substring(pos + 1);

			while (tmp.indexOf("$classname") >= 0) tmp = tmp.replace("$classname", name);
			while (tmp.indexOf("$(classname)") >= 0) tmp = tmp.replace("$(classname)", name);
			while (tmp.indexOf("${classname}") >= 0) tmp = tmp.replace("${classname}", name);

			while (tmp.indexOf("$filename") >= 0) tmp = tmp.replace("$filename", name);
			while (tmp.indexOf("$(filename)") >= 0) tmp = tmp.replace("$(filename)", name);
			while (tmp.indexOf("${filename}") >= 0) tmp = tmp.replace("${filename}", name);

            SetCgiAccess(tmp, cgipath.access());

            if (document != null){
                SetCgiDoc(tmp, GetDocString(document.request()), GetDocString(document.response()), document.remark());
            }

			if (timertask != null){
				SetCgiExtdata(tmp, "timertask=" + timertask.value());
				SetCgiAccess(tmp, "protect");
			}

			if (dailytask != null){
				SetCgiExtdata(tmp, "dailytask=" + dailytask.value());
				SetCgiAccess(tmp, "protect");
			}

			return tmp.getBytes();
		}
		catch (Exception e){
			e.printStackTrace();

			return null;
		}
	}

	public void process(HttpRequest request, HttpResponse response) throws Exception{
		String path = request.get("path");
		ConfigFile dbcfg = new ConfigFile();

		try {
            System.load(path + "etc/plugin/bin/InitSystem.so");
        }
        catch (UnsatisfiedLinkError e){
            System.load(path + "etc/plugin/bin/InitSystem.dll");
        }

		String cfgpath = WebApp.GetConfig("DATABASE_CONFIGFILE_PATH");

		if (cfgpath.isEmpty()) cfgpath = path + "etc/dbconfig.lua";

		if (dbcfg.open(cfgpath)){
			int port = dbcfg.getInt("PORT");
			String host = dbcfg.get("HOST");
			String name = dbcfg.get("NAME");
			String user = dbcfg.get("USER");
			String passwd = dbcfg.get("PASSWORD");
			String dllpath = dbcfg.get("DLLPATH");

            try {
                dbconnmaxlen = Integer.parseInt(dbcfg.get("MAXSIZE"));
            }
            catch (Exception e){
            }

            try {
                dbconntimeout = Integer.parseInt(dbcfg.get("TIMEOUT"));
            }
            catch (Exception e){
            }

			if (Utils.IsNotEmpty(name) && initdb(null, dllpath, host, port, name, user, passwd)){
				DBConnect dbconn = DBConnect.Connect();

				try{
					String sql = "SELECT ID,TYPE,HOST,PORT,NAME,USER,PASSWD FROM T_XG_DBETC WHERE ENABLED>0";

                    ArrayList<DBConfig> vec = dbconn.selectList(DBConfig.class, sql);

                    for (DBConfig item : vec) initdb(item.id, item.type, item.host, item.port, item.name, item.user, item.passwd);
				}
				catch(Exception e){
					e.printStackTrace();
				}
				finally{
					Utils.Close(dbconn);
				}
			}

            host = dbcfg.get("REDIS_HOST");
            port = dbcfg.getInt("REDIS_PORT");
            passwd = dbcfg.get("REDIS_PASSWORD");

            if (Utils.IsNotEmpty(host)){
                try {
                    RedisConnect.GetPool().init(host, port, passwd, false).get();

                    LogFile.Trace(LogFile.IMP, "initialize redis[%s:%d] success", host, port);
                }
                catch(Exception e){
                    LogFile.Trace(LogFile.ERR, "initialize redis[%s:%d] failed", host, port);
                }
            }
        }
	}
	public boolean initdb(String dbid, String type, String host, int port, String name, String user, String passwd){
		DBConnect.Config db = new DBConnect.Config();

		db.user = user;
		db.passwd = passwd;

		name = Utils.Translate(name);
        type = type.toLowerCase();

		if (type.indexOf("mysql") >= 0){
			db.url = String.format("jdbc:mysql://%s:%d/%s", host, port, name);
		}
		else if (type.indexOf("oracle") >= 0){
			db.url = String.format("jdbc:oracle:thin:@%s:%d/%s", host, port, name);
		}
		else if (type.indexOf("postgres") >= 0){
			db.url = String.format("jdbc:postgresql://%s:%d/%s", host, port, name);
		}
		else if (type.indexOf("sqlite") >= 0){
			db.url = String.format("jdbc:sqlite:%s", name);
		}

		if (db.url.isEmpty()) return false;

		try{
			DBConnect dbconn = null;

			if (dbid == null){
				dbconn = DBConnect.GetPool().init(db, dbconnmaxlen, dbconntimeout).get();
			}
			else{
				dbconn = DBConnect.GetPool(dbid).init(db, dbconnmaxlen, dbconntimeout).get();
			}

			LogFile.Trace(LogFile.IMP, "initialize database[%s] success", db.url);

			Utils.Close(dbconn);

			return true;
		}
		catch(Exception e){
			LogFile.Trace(LogFile.ERR, "initialize database[%s] failed[%s]", db.url, e.getMessage());

			e.printStackTrace();

			return false;
		}
	}
}